package cn.hist.hfp.util;

import cn.hist.hfp.exception.BusinessException;
import cn.hist.hfp.exception.ErrorCode;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Getter
@Setter
@Component
public class TokenUtil {

    static final String CLAIM_KEY_IDENTITY = "sub";
    static final String CLAIM_KEY_CREATED = "created";

    @Value("${hfp.token.secret}")
    private String secret;

    @Value("${hfp.token.expiration}")
    private Long expiration;

    private Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }

    public String generateToken(String username) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(CLAIM_KEY_IDENTITY, username);
        claims.put(CLAIM_KEY_CREATED, new Date());
        return generateToken(claims);
    }

    private String generateToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.HS512, this.secret)
                .compact();
    }

    private Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }

    public String getIdentityInfo(String token) {
        String indentity;
        try {
            final Claims claims = getClaimsFromToken(token);
            indentity = claims.getSubject();
        } catch (Exception e) {
            indentity = null;
        }
        return indentity;
    }

    public Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        if (expiration == null)
            return true;
        return expiration.before(new Date());
    }

    public Date getExpirationDateFromToken(String token) {
        Date expiration;
        try {
            final Claims claims = getClaimsFromToken(token);
            expiration = claims.getExpiration();
        } catch (Exception e) {
            expiration = null;
        }
        return expiration;
    }

    // /**
    //  * Token失效校验
    //  * @param token token字符串
    //  * @param loginInfo 用户信息
    //  * @return
    //  */
    // public Boolean validateToken(String token, LoginInfo loginInfo) {
    //     final String username = getIdentityInfo(token);
    //     return (
    //             username.equals(loginInfo.getUsername())
    //                     && !isTokenExpired(token));
    // }

    public String refreshToken(String token) {
        final Claims claims = this.getClaimsFromToken(token);
        if (claims == null)
            throw new BusinessException(ErrorCode.INFO_EXPIRED);
        claims.put(CLAIM_KEY_CREATED, new Date());
        return generateToken(claims);
    }
}

